package _79

import (
	"bytes"
)

/*
时间复杂度：O(k1N + k2) k1表示调用ToString()的次数,ToString时间复杂度为N, k2表示调用其他操作的次数
空间复杂度：O(N) 用来存储每一个数位的切片长度

flips 美[flɪps] 快速翻转
Go中^表示作为双目运算符时表示按位异或
作为单目运算符时表示按位取反(与其他语言中的~等效)

懒标记法
*/

// 字段名不能跟方法名相同(例如不能同时有字段名和方法名为Count)
type Bitset struct {
	Bits  []byte
	// 懒标记法,每次调用Flip方法的时候都只更改Flips的状态
	// 直到调用ToString方法时才会真正执行翻转操作
	Flips bool // 美[flɪps] 快速翻转
	Cnt int
}

func Constructor(size int) Bitset {
	bits := bytes.Repeat([]byte{'0'}, size)
	return Bitset{
		Bits:  bits,
		Flips: false,
		Cnt:   0,
	}
}

func (this *Bitset) Fix(idx int) {
	// 如果不需要翻转,则this.Flips为false, 此时只需要对'0'转换为'1'即可
	// 如果this.Flips为true,则需要翻转,此时为'1'的原本是'0', 所以需要对为'1'的数翻转为'0'(Flips为true时的'0'就相当于Flips为false时的'1')
	if (this.Bits[idx] == '1') == this.Flips {
		this.Bits[idx] ^= 1
		this.Cnt++
	}
}

func (this *Bitset) Unfix(idx int) {
	if (this.Bits[idx] == '0') == this.Flips {
		this.Bits[idx] ^= 1
		this.Cnt--
	}
}

func (this *Bitset) Flip() {
	this.Flips = !this.Flips
	this.Cnt = len(this.Bits) - this.Cnt
}

func (this *Bitset) All() bool {
	return this.Cnt == len(this.Bits)
}

func (this *Bitset) One() bool {
	return this.Cnt > 0
}

func (this *Bitset) Count() int {
	return this.Cnt
}

func (this *Bitset) ToString() string {
	if this.Flips {
		t := make([]byte, len(this.Bits))
		for i, ch := range this.Bits {
			t[i] = ch ^ 1
		}
		return string(t)
	}
	return string(this.Bits)
}


/**
 * Your Bitset object will be instantiated and called as such:
 * obj := Constructor(size);
 * obj.Fix(idx);
 * obj.Unfix(idx);
 * obj.Flip();
 * param_4 := obj.All();
 * param_5 := obj.One();
 * param_6 := obj.Count();
 * param_7 := obj.ToString();
 */

///*
//时间复杂度：O()
//空间复杂度：O()
//
//*/
//
//type Bitset struct {
//	b     []byte
//	rb    []byte
//	count int
//}
//
//func Constructor(size int) Bitset {
//	b := make([]byte, size)
//	rb := make([]byte, size)
//	for i := range b {
//		b[i] = '0'
//		rb[i] = '1'
//	}
//	return Bitset{
//		b:     b,
//		rb:    rb,
//		count: 0,
//	}
//}
//
//func (this *Bitset) Fix(idx int) {
//	if this.b[idx] == '0' {
//		this.count++
//		this.b[idx] = '1'
//	}
//	this.rb[idx] = '0'
//}
//
//func (this *Bitset) Unfix(idx int) {
//	if this.b[idx] == '1' {
//		this.count--
//		this.b[idx] = '0'
//	}
//	this.rb[idx] = '1'
//}
//
//func (this *Bitset) Flip() {
//	this.b, this.rb = this.rb, this.b
//	this.count = len(this.b) - this.count
//}
//
//func (this *Bitset) All() bool {
//	return this.count == len(this.b)
//}
//
//func (this *Bitset) One() bool {
//	return this.count > 0
//}
//
//func (this *Bitset) Count() int {
//	return this.count
//}
//
//func (this *Bitset) ToString() string {
//	return string(this.b)
//}

/**
 * Your Bitset object will be instantiated and called as such:
 * obj := Constructor(size);
 * obj.Fix(idx);
 * obj.Unfix(idx);
 * obj.Flip();
 * param_4 := obj.All();
 * param_5 := obj.One();
 * param_6 := obj.Count();
 * param_7 := obj.ToString();
 */